#include "gtest/gtest.h" 
#include "helper/rocksdb/NumberComparator.h"

#include "helper/rocksdb/Rocksdb.h"
#include "helper/rocksdb/Table.h"

#include "helper/rocksdb/SliceUtil.h"


using Rocksdb = helper::rocksdb::Rocksdb;
using SliceUtil = helper::rocksdb::SliceUtil;
using NumberComparator = helper::rocksdb::NumberComparator;

TEST(NumberComparatorTest, testMain){
    NumberComparator nc;
    ASSERT_EQ(std::string(nc.Name()), std::string("helper.NumberComparator"));
    int64_t a = 10;
    int64_t b = 12;
    auto && left = SliceUtil::fromNumber<int64_t>(a);
    auto && right = SliceUtil::fromNumber<int64_t>(b);
    ASSERT_TRUE( 0 > nc.Compare(left, right));
}


using Slice = ::rocksdb::Slice;
TEST(NumberComparatorTest, testRocksdb){
    const std::string dirname_mycomparator = "test-rocksdb-comparator.db";
	const std::string _defTabName = "default";

    std::unique_ptr<NumberComparator> ncomp(new NumberComparator);
	Rocksdb db(dirname_mycomparator, ncomp.get());

    db.createIfMissing();
    ASSERT_TRUE(db.isOpened());

	auto && p= db.isTableExist(_defTabName);
	ASSERT_TRUE(p.first);

	ASSERT_TRUE(db.tables().size() >= 1);

    auto table = db.getTable(_defTabName);

    ASSERT_TRUE(table->put(SliceUtil::fromNumber<int64_t>(64), "string").ok());
    ASSERT_TRUE(table->put(SliceUtil::fromNumber<int64_t>(63), "string").ok());
    ASSERT_TRUE(table->put(SliceUtil::fromNumber<int64_t>(62), "string").ok());
    ASSERT_TRUE(table->put(SliceUtil::fromNumber<int64_t>(3), "string").ok());
    ASSERT_TRUE(table->put(SliceUtil::fromNumber<int64_t>(1), "string").ok());

    auto print = [](const Slice & key, const Slice & value) -> bool{
        std::cout << SliceUtil::toNumber<int64_t>(key) << ":" << value.ToString() << std::endl;
        return true;
    };

    {
        std::cout << "print all:" << std::endl;
        table->foreach(print);
    }

    {
        std::cout << "print all:62->end:" << std::endl;
        auto && start = SliceUtil::fromNumber<int64_t>(62);
        table->foreach(print, start);
    }

    {
        std::cout << "print [1,63):" << std::endl;
        table->foreach(print, SliceUtil::fromNumber<int64_t>(1), SliceUtil::fromNumber<int64_t>(63));
    }

    //create stream database
    {
        const std::string tabName = "stream";
        auto table = db.createTable(tabName);
        ASSERT_TRUE(table != nullptr);
        
        std::cout << "tabName:stream:"  << std::endl;
        table->foreach(print);

        ASSERT_TRUE(table->put((int64_t)64, "string64").ok());

        db.closeTable(tabName);
    }

    db.close();
    ASSERT_FALSE(db.isOpened());


    ASSERT_TRUE(Rocksdb::destroy(dirname_mycomparator));
}
